Skip to main content

Edit Indication

Form fields in Kyber support rendering an indicator that the field has been edited and the option to include the previous value. To enable this either the showEditedIndicator or showPreviousValuesAfterEdit props can be used on the Form component.

The fields initial value must be set and indicators will only be rendered if the field value has been changed from its initial value.

Show Edited Indicator

Slider and Range fields do not currently support edit indication.

Result
Loading...
Live Editor
const selectItems = [
	{
		id: 'one',
		editedKey: 'one',
		textValue: 'One',
		content: (
			<>
				One<div>Juice box</div>
			</>
		),
	},
	{ id: 'two', editedKey: 'two', textValue: 'Two', content: <>Two</> },
	{ id: 'three', editedKey: 'three', textValue: 'Three', content: <>Three</> },
	{ id: 'four', editedKey: 'four', textValue: 'Four', content: <>Four</> },
];

const milestoneOptions = [
	{
		id: 'Start',
		defaultValue: '12/31/2022',
		label: 'Start (12/31/2022)',
	},
	{
		id: 'Duration',
		label: 'Duration',
		defaultValue: 4,
	},
	{
		id: 'CalendarYear',
		defaultValue: 2050,
		label: 'Calendar Year',
	},
	{
		id: 'ClientIs',
		defaultValue: 50,
		label: 'When client is',
		milestoneDate: '05/30/1980',
	},
];

render(
	<Form
		showEditedIndicator
		initialValues={{
			'textfield': 'Wow',
			'numberField': 10,
			'date': '2023-12-31',
			'autoComplete': 'Two',
			'select': 'one',
			'select-w-items': 'two',
			'multiSelect': ['one', 'two'],
			'multiSelect-w-items': ['three', 'four'],
			'milestone': {
				type: 'Start',
				value: '12/31/2022',
			},
			'milestone-2': {
				type: 'Duration',
				value: 4,
			},
			'start-stop': {
				startValue: {
					type: 'Start',
					value: '12/31/2022',
				},
				stopValue: {
					type: 'Duration',
					value: 10,
				},
			},
			'start-stop-2': {
				startValue: {
					type: 'CalendarYear',
					value: 2050,
				},
				stopValue: {
					type: 'Duration',
					value: 10,
				},
			},
			'favoriteFruits': ['apples', 'melons'],
			'favoriteAnimal': 'lion',
			'action': false,
			'agree': true,
			'color': '#663399',
		}}
		onSubmit={(values, { setSubmitting }) => {
			console.log(values);
			setSubmitting(false);
		}}
	>
		<FormField>
			<TextField name="textfield" label="TextField" />
		</FormField>

		<FormField>
			<NumberField
				name="numberField"
				label="NumberField"
				description="NumberField value only changes on blur"
			/>
		</FormField>

		<FormField>
			<DatePicker name="date" label="Date" />
		</FormField>

		<FormField>
			<AutoComplete name="autoComplete" label="AutoComplete">
				{selectItems.map(({ id, editedKey, textValue, content }) => (
					<Item key={id} editedKey={editedKey} textValue={textValue}>
						{content}
					</Item>
				))}
			</AutoComplete>
		</FormField>

		<FormField>
			<Select name="select" label="Select">
				{selectItems.map(({ id, editedKey, textValue, content }) => (
					<Item key={id} editedKey={editedKey} textValue={textValue}>
						{content}
					</Item>
				))}
			</Select>
		</FormField>

		<FormField>
			<Select name="select-w-items" label="Select w/Items" items={selectItems}>
				{({ id, content, ...restProps }) => (
					<Item key={id} {...restProps}>
						{content}
					</Item>
				)}
			</Select>
		</FormField>

		<FormField>
			<MultiSelect name="multiSelect" label="MultiSelect">
				{selectItems.map(({ id, editedKey, textValue, content }) => (
					<Item key={id} editedKey={editedKey} textValue={textValue}>
						{content}
					</Item>
				))}
			</MultiSelect>
		</FormField>

		<FormField>
			<MultiSelect name="multiSelect-w-items" label="MultiSelect w/Items" items={selectItems}>
				{({ id, content, ...restProps }) => (
					<Item key={id} {...restProps}>
						{content}
					</Item>
				)}
			</MultiSelect>
		</FormField>

		<Divider label="Milestone" className="k-my-3" />

		<FormField>
			<Milestone label="Milestone" name="milestone" options={milestoneOptions} />
		</FormField>

		<FormField>
			<Milestone
				label="Milestone (Default Duration)"
				name="milestone-2"
				options={milestoneOptions}
			/>
		</FormField>

		<Divider label="StartStop" className="k-my-3" />

		<FormField>
			<StartStop name="start-stop" startOptions={milestoneOptions} stopOptions={milestoneOptions} />
		</FormField>

		<FormField>
			<StartStop
				name="start-stop-2"
				startOptions={milestoneOptions}
				stopOptions={milestoneOptions}
			/>
		</FormField>

		<Divider className="k-my-3" />

		<FormField>
			<CheckboxGroup label="Favorite fruits" name="favoriteFruits">
				<CheckboxGroup.Item value="apples" label="Apples" textValue="Apples" />
				<CheckboxGroup.Item value="pears" label="Pears" textValue="Pears" />
				<CheckboxGroup.Item value="bananas" label="Bananas" textValue="Bananas" />
				<CheckboxGroup.Item value="melons" label="Melons" textValue="Melons" />
				<CheckboxGroup.Item value="strawberries" label="Strawberries" textValue="Strawberries" />
			</CheckboxGroup>
		</FormField>

		<FormField>
			<RadioGroup label="Favorite animal" name="favoriteAnimal">
				<RadioGroup.Item value="lion" label="Lion" textValue="Lion" />
				<RadioGroup.Item value="tiger" label="Tiger" textValue="Tiger" />
				<RadioGroup.Item value="bear" label="Bear" textValue="Bear" />
				<RadioGroup.Item value="moose" label="Moose" textValue="Moose" />
				<RadioGroup.Item value="goose" label="Goose" textValue="Goose" />
			</RadioGroup>
		</FormField>

		<FormField>
			<Switch name="action" label="Action" />
		</FormField>

		<FormField>
			<Checkbox name="agree" label="Agree" />
		</FormField>

		<FormField>
			<ColorField name="color" label="Color" />
		</FormField>
	</Form>,
);

Showing Original Values After Edit

By default, edit indicator text will be prefixed with 'Original value:'. This can be customized by providing a string to the previousValuesAfterEditPrefix prop on the Form component.

If an editedText prop is provided to the FormField then the showPreviousValuesAfterEdit and previousValuesAfterEditPrefix props will have no effect and the provided editedText will be used instead.

Result
Loading...
Live Editor
const selectItems = [
	{
		id: 'one',
		editedKey: 'one',
		textValue: 'One',
		content: (
			<>
				One<div>Juice box</div>
			</>
		),
	},
	{ id: 'two', editedKey: 'two', textValue: 'Two', content: <>Two</> },
	{ id: 'three', editedKey: 'three', textValue: 'Three', content: <>Three</> },
	{ id: 'four', editedKey: 'four', textValue: 'Four', content: <>Four</> },
];

const milestoneOptions = [
	{
		id: 'Start',
		defaultValue: '12/31/2022',
		label: 'Start (12/31/2022)',
	},
	{
		id: 'Duration',
		label: 'Duration',
		defaultValue: 4,
	},
	{
		id: 'CalendarYear',
		defaultValue: 2050,
		label: 'Calendar Year',
	},
	{
		id: 'ClientIs',
		defaultValue: 50,
		label: 'When client is',
		milestoneDate: '05/30/1980',
	},
];

render(
	<Form
		showPreviousValuesAfterEdit
		initialValues={{
			'textfield': 'Wow',
			'numberField': 10,
			'date': '2023-12-31',
			'autoComplete': 'Two',
			'select': 'one',
			'select-w-items': 'two',
			'multiSelect': ['one', 'two'],
			'multiSelect-w-items': ['three', 'four'],
			'milestone': {
				type: 'Start',
				value: '12/31/2022',
			},
			'milestone-2': {
				type: 'Duration',
				value: 4,
			},
			'start-stop': {
				startValue: {
					type: 'Start',
					value: '12/31/2022',
				},
				stopValue: {
					type: 'Duration',
					value: 10,
				},
			},
			'start-stop-2': {
				startValue: {
					type: 'CalendarYear',
					value: 2050,
				},
				stopValue: {
					type: 'Duration',
					value: 10,
				},
			},
			'favoriteFruits': ['apples', 'melons'],
			'favoriteAnimal': 'lion',
			'action': false,
			'agree': true,
			'color': '#663399',
			'range': {
				selectedStartValue: 2,
				selectedEndValue: 8,
			},
			'slider': 5,
		}}
		onSubmit={(values, { setSubmitting }) => {
			console.log(values);
			setSubmitting(false);
		}}
	>
		<FormField>
			<TextField name="textfield" label="TextField" />
		</FormField>

		<FormField>
			<NumberField name="numberField" label="NumberField" />
		</FormField>

		<FormField>
			<DatePicker name="date" label="Date" />
		</FormField>

		<FormField>
			<AutoComplete name="autoComplete" label="AutoComplete">
				{selectItems.map(({ id, editedKey, textValue, content }) => (
					<Item key={id} editedKey={editedKey} textValue={textValue}>
						{content}
					</Item>
				))}
			</AutoComplete>
		</FormField>

		<FormField>
			<Select name="select" label="Select">
				{selectItems.map(({ id, editedKey, textValue, content }) => (
					<Item key={id} editedKey={editedKey} textValue={textValue}>
						{content}
					</Item>
				))}
			</Select>
		</FormField>

		<FormField>
			<Select name="select-w-items" label="Select w/Items" items={selectItems}>
				{({ id, content, ...restProps }) => (
					<Item key={id} {...restProps}>
						{content}
					</Item>
				)}
			</Select>
		</FormField>

		<FormField>
			<MultiSelect name="multiSelect" label="MultiSelect">
				{selectItems.map(({ id, editedKey, textValue, content }) => (
					<Item key={id} editedKey={editedKey} textValue={textValue}>
						{content}
					</Item>
				))}
			</MultiSelect>
		</FormField>

		<FormField>
			<MultiSelect name="multiSelect-w-items" label="MultiSelect w/Items" items={selectItems}>
				{({ id, content, ...restProps }) => (
					<Item key={id} {...restProps}>
						{content}
					</Item>
				)}
			</MultiSelect>
		</FormField>

		<Divider label="Milestone" className="k-my-3" />

		<FormField>
			<Milestone label="Milestone" name="milestone" options={milestoneOptions} />
		</FormField>

		<FormField>
			<Milestone
				label="Milestone (Default Duration)"
				name="milestone-2"
				options={milestoneOptions}
			/>
		</FormField>

		<Divider label="StartStop" className="k-my-3" />

		<FormField>
			<StartStop name="start-stop" startOptions={milestoneOptions} stopOptions={milestoneOptions} />
		</FormField>

		<FormField>
			<StartStop
				name="start-stop-2"
				startOptions={milestoneOptions}
				stopOptions={milestoneOptions}
			/>
		</FormField>

		<Divider className="k-my-3" />

		<FormField>
			<CheckboxGroup label="Favorite fruits" name="favoriteFruits">
				<CheckboxGroup.Item value="apples" label="Apples" textValue="Apples" />
				<CheckboxGroup.Item value="pears" label="Pears" textValue="Pears" />
				<CheckboxGroup.Item value="bananas" label="Bananas" textValue="Bananas" />
				<CheckboxGroup.Item value="melons" label="Melons" textValue="Melons" />
				<CheckboxGroup.Item value="strawberries" label="Strawberries" textValue="Strawberries" />
			</CheckboxGroup>
		</FormField>

		<FormField>
			<RadioGroup label="Favorite animal" name="favoriteAnimal">
				<RadioGroup.Item value="lion" label="Lion" textValue="Lion" />
				<RadioGroup.Item value="tiger" label="Tiger" textValue="Tiger" />
				<RadioGroup.Item value="bear" label="Bear" textValue="Bear" />
				<RadioGroup.Item value="moose" label="Moose" textValue="Moose" />
				<RadioGroup.Item value="goose" label="Goose" textValue="Goose" />
			</RadioGroup>
		</FormField>

		<FormField>
			<Switch name="action" label="Action" />
		</FormField>

		<FormField>
			<Checkbox name="agree" label="Agree" />
		</FormField>

		<FormField>
			<ColorField name="color" label="Color" />
		</FormField>

		<FormField>
			<Range name="range" label="Range" minValue={0} maxValue={10} />
		</FormField>

		<FormField>
			<Slider name="slider" label="Slider" min={0} max={10} />
		</FormField>
	</Form>,
);

Optionally disabling the edited indicators for specific fields

This is useful if a specific field needs to not show the indicator and edited text despite the Form's showEditedIndicator or showPreviousValuesAfterEdit prop being true.

Result
Loading...
Live Editor
<Form
	showPreviousValuesAfterEdit
	initialValues={{
		enabled: 'This field has edit indication',
		disabled: 'This field does not have edit indication',
	}}
	onSubmit={(values, { setSubmitting }) => {
		console.log(values);
		setSubmitting(false);
	}}
>
	<FormField>
		<TextField name="enabled" label="Edit indicator enabled" />
	</FormField>

	<FormField showEditedIndicator={false}>
		<TextField name="disabled" label="Edit indicator disabled" />
	</FormField>
</Form>